package com.jarcms.smdcmanage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jarcms.smdcmanage.entity.Order;
import com.jarcms.smdcmanage.entity.OrderDetail;
import com.jarcms.smdcmanage.entity.User;
import com.jarcms.smdcmanage.exception.BusinessException;
import com.jarcms.smdcmanage.mapper.OrderDetailMapper;
import com.jarcms.smdcmanage.mapper.OrderMapper;
import com.jarcms.smdcmanage.mapper.UserMapper;
import com.jarcms.smdcmanage.service.OrderService;
import com.jarcms.smdcmanage.vo.OrderVO;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.dom4j.Element;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private UserMapper userMapper;

    @Value("${wx.appid}")
    private String APP_ID;

    @Value("${wx.mchid}")
    private String MCH_ID;

    @Value("${wx.key}")
    private String API_KEY; // 商户支付密钥

     @Value("${wx.notify-url}")
    private String NOTIFY_URL; // 商户支付密钥

    private static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createOrder(OrderVO orderVO) {
        // 生成订单号
        String orderNo = generateOrderNo();
        Order order = new Order();
        BeanUtils.copyProperties(orderVO, order);
        order.setOrderNo(orderNo);
        order.setStatus(0); // 待支付
        order.setPayMethod(0);
        // 保存订单
        save(order);

        // 保存订单详情
        List<OrderDetail> orderDetails = orderVO.getOrderDetails();
        if (orderDetails != null && !orderDetails.isEmpty()) {
            for (OrderDetail orderDetail : orderDetails) {
                orderDetail.setOrderId(order.getId());
                orderDetailMapper.insert(orderDetail);
            }
        }

        return orderNo;
    }

    @Override
    public Map<String, Object> payOrder(String orderNo) {
        // 查询订单
        Order order = getOrderByOrderNo(orderNo);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 0) {
            throw new BusinessException("订单状态不正确");
        }

        // 调用微信支付接口
        Map<String, Object> responseMap = new HashMap<>();
        try {
            //订单金额
            BigDecimal amount = order.getTotalAmount();
            // 构建统一下单请求数据
            Map<String, String> orderData = new TreeMap<>();
            orderData.put("appid", APP_ID);
            orderData.put("mch_id", MCH_ID);
            orderData.put("nonce_str", generateNonceStr(32));
            orderData.put("body", "商品描述");
            orderData.put("out_trade_no", orderNo); // 商户系统内部订单号
            orderData.put("total_fee", String.valueOf( amount.doubleValue() * 100)); // 订单总金额，单位为分
            // TODO 客户端IP地址，这里使用本地测试
            orderData.put("spbill_create_ip", "127.0.0.1");
            orderData.put("notify_url", NOTIFY_URL); // 支付结果通知地址
            orderData.put("trade_type", "JSAPI");
            // 查询用户信息
            User user = userMapper.selectById(order.getUserId());
            orderData.put("openid", user.getOpenid()); // 用户openid，需要根据实际情况获取

            // 生成签名
            orderData.put("sign", generateSign(orderData));

            // 发送统一下单请求
            String xmlRequest = buildXml(orderData);
            String xmlResponse = sendPostRequest(xmlRequest);

            // 解析响应XML
            Document document = parseXml(xmlResponse);
            Element rootElement = document.getRootElement();

            if ("SUCCESS".equals(rootElement.elementTextTrim("return_code")) && "SUCCESS".equals(rootElement.elementTextTrim("result_code"))) {
                String prepayId = rootElement.elementTextTrim("prepay_id");

                // 构建前端调起支付所需的数据
                Map<String, String> paymentData = new TreeMap<>();
                paymentData.put("appId", APP_ID);
                paymentData.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
                paymentData.put("nonceStr", generateNonceStr(32));
                paymentData.put("package", "prepay_id=" + prepayId);
                paymentData.put("signType", "MD5");
                paymentData.put("paySign", generateSign(paymentData));

                responseMap.put("code", 0);
                responseMap.putAll(paymentData);
            } else {
                responseMap.put("code", -1);
                responseMap.put("message", rootElement.elementTextTrim("return_msg") != null ? rootElement.elementTextTrim("return_msg") : "统一下单失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            responseMap.put("code", -1);
            responseMap.put("message", "服务器错误");
        }

        // 模拟支付成功
       /* order.setStatus(1); // 已完成
        order.setPayTime(LocalDateTime.now());
        updateById(order);*/

        return responseMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(Long id) {
        // 查询订单
        Order order = getById(id);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 0) {
            throw new BusinessException("只有待支付的订单才能取消");
        }

        // 更新订单状态
        order.setStatus(2); // 已取消
        order.setCancelTime(LocalDateTime.now());
        return updateById(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeOrder(Long id) {
        Order order = getById(id);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 0) {
            throw new BusinessException("订单状态不正确，只能完成待支付的订单");
        }

        order.setStatus(1); // 已完成
        return updateById(order);
    }

    @Override
    public OrderVO getOrderDetail(Long id) {
        // 查询订单
        Order order = getById(id);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        // 查询订单详情
        LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderDetail::getOrderId, id);
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(queryWrapper);

        // 查询用户信息
        User user = userMapper.selectById(order.getUserId());

        // 组装VO
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        orderVO.setOrderDetails(orderDetails);
        if (user != null) {
            orderVO.setNickname(user.getNickname());
            orderVO.setPhone(user.getPhone());
        }

        return orderVO;
    }

    @Override
    public OrderVO getOrderDetailByOrderNo(String orderNo) {
        // 查询订单
        Order order = getOrderByOrderNo(orderNo);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        // 查询订单详情
        LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderDetail::getOrderId, order.getId());
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(queryWrapper);

        // 查询用户信息
        User user = userMapper.selectById(order.getUserId());

        // 组装VO
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        orderVO.setOrderDetails(orderDetails);
        if (user != null) {
            orderVO.setNickname(user.getNickname());
            orderVO.setPhone(user.getPhone());
        }

        return orderVO;
    }

    @Override
    public Page<OrderVO> page(int page, int size, Long userId, Integer status, String orderNo, String beginTime, String endTime) {
        // 查询订单
        Page<Order> orderPage = new Page<>(page, size);
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(userId != null, Order::getUserId, userId);
        queryWrapper.eq(status != null, Order::getStatus, status);
        queryWrapper.like(StringUtils.hasText(orderNo), Order::getOrderNo, orderNo);

        // 时间范围查询
        if (StringUtils.hasText(beginTime) && StringUtils.hasText(endTime)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime begin = LocalDateTime.parse(beginTime, formatter);
            LocalDateTime end = LocalDateTime.parse(endTime, formatter);
            queryWrapper.between(Order::getCreateTime, begin, end);
        }

        queryWrapper.orderByDesc(Order::getCreateTime);
        page(orderPage, queryWrapper);

        // 组装VO
        List<Order> records = orderPage.getRecords();
        List<OrderVO> orderVOList = new ArrayList<>();

        if (!records.isEmpty()) {
            // 获取所有订单ID
            List<Long> orderIds = records.stream().map(Order::getId).collect(Collectors.toList());
            // 查询所有订单详情
            LambdaQueryWrapper<OrderDetail> detailQueryWrapper = new LambdaQueryWrapper<>();
            detailQueryWrapper.in(OrderDetail::getOrderId, orderIds);
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(detailQueryWrapper);
            // 按订单ID分组
            Map<Long, List<OrderDetail>> detailMap = orderDetails.stream()
                    .collect(Collectors.groupingBy(OrderDetail::getOrderId));

            // 获取所有用户ID
            List<Long> userIds = records.stream().map(Order::getUserId).distinct().collect(Collectors.toList());
            // 查询所有用户
            LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
            userQueryWrapper.in(User::getId, userIds);
            List<User> users = userMapper.selectList(userQueryWrapper);
            // 按用户ID分组
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));

            // 组装VO
            for (Order order : records) {
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(order, orderVO);
                // 设置订单详情
                orderVO.setOrderDetails(detailMap.get(order.getId()));
                // 设置用户信息
                User user = userMap.get(order.getUserId());
                if (user != null) {
                    orderVO.setNickname(user.getNickname());
                    orderVO.setPhone(user.getPhone());
                }
                orderVOList.add(orderVO);
            }
        }

        // 创建VO分页对象
        Page<OrderVO> orderVOPage = new Page<>(page, size, orderPage.getTotal());
        orderVOPage.setRecords(orderVOList);

        return orderVOPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean payNotify(String orderNo) {
        // 查询订单
        Order order = getOrderByOrderNo(orderNo);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 0) {
            return true; // 订单已处理，直接返回成功
        }

        // 更新订单状态
        order.setStatus(1); // 已完成
        order.setPayTime(LocalDateTime.now());
        return updateById(order);
    }

    @Override
    public int countByTime(LocalDateTime startTime, LocalDateTime endTime) {
        return orderDetailMapper.countByTime(startTime,endTime);
    }

    @Override
    public BigDecimal sumAmountByTime(LocalDateTime startTime, LocalDateTime endTime) {
        return orderDetailMapper.sumAmountByTime(startTime,endTime);
    }

    /**
     * 根据订单号查询订单
     */
    private Order getOrderByOrderNo(String orderNo) {
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getOrderNo, orderNo);
        return getOne(queryWrapper);
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        return System.currentTimeMillis() + String.format("%06d", (int) (Math.random() * 1000000));
    }



    private String generateNonceStr(int length) {
        StringBuilder sb = new StringBuilder(length);
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(36);
            char c = (char) (index <= 9 ? '0' + index : 'a' + index - 10);
            sb.append(c);
        }
        return sb.toString();
    }

    private String generateSign(Map<String, String> params) throws NoSuchAlgorithmException {
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (!entry.getValue().isEmpty()) {
                stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        stringBuilder.append("key=").append(API_KEY);

        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder(digest.length * 2);
        for (byte b : digest) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString().toUpperCase();
    }

    private String buildXml(Map<String, String> data) {
        StringBuilder xml = new StringBuilder("<xml>");
        for (Map.Entry<String, String> entry : data.entrySet()) {
            xml.append("<").append(entry.getKey()).append(">").append(entry.getValue()).append("</").append(entry.getKey()).append(">");
        }
        xml.append("</xml>");
        return xml.toString();
    }

    private String sendPostRequest(String xmlRequest) throws Exception {
        HttpClient client = new HttpClient();
        PostMethod postMethod = new PostMethod(UNIFIED_ORDER_URL);
        RequestEntity entity = new StringRequestEntity(xmlRequest, "application/xml", StandardCharsets.UTF_8.name());
        postMethod.setRequestEntity(entity);

        int statusCode = client.executeMethod(postMethod);
        if (statusCode == HttpStatus.SC_OK) {
            return postMethod.getResponseBodyAsString();
        } else {
            throw new Exception("HTTP请求失败，状态码：" + statusCode);
        }
    }

    private Document parseXml(String xml) throws DocumentException {
        SAXReader reader = new SAXReader();
        InputStream inputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
        return reader.read(inputStream);
    }

}
